package com.zhny.view;

import com.zhny.meddleware.IViewMessenger;
import com.zhny.meddleware.SenderProxy;
import com.zhny.protocol_v3_008.constant.DeviceType;
import com.zhny.util.XMLReaderUtil;
import com.zhny.vo.LogItem;
import com.zhny.vo.XMLSite;
import org.jb2011.lnf.beautyeye.ch3_button.BEButtonUI;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.List;
import java.util.logging.Logger;

/**
 * @Author 侯俊杰
 * @Date 2017/11/8
 * @Time 20:14
 **/
public class TelemeteringJPanel implements IViewMessenger {


    private JPanel telemeteringJPanel;
    private Logger logger = Logger.getLogger("TelemeteringJPanel");

    private JPanel topJPanel;
    private JPanel bottomJPanel;

    //在topJpanel中
    private JLabel baseSelectLabel;
    private JComboBox baseSelectComboBox;
    private JLabel siteSelectLabel;
    private JComboBox siteSelectComboBox;

    //在bottomJPanel中
    JButton mSwitch = new JButton();
    private static int btcCount=0;
    //数据项
    private XMLSite currentSite;
    private Vector<String> basesNames;
    private List<ArrayList<Boolean>> switchFlagses;//这里的index第一层和base索引对应，第二层和site索引对应
    private DefaultListModel mListData = new DefaultListModel();

    public static int maxListSize = 10000;//mLogDetails的最大长度
    private List<Map<String,String>> mLogDetails = new ArrayList<>();//存放每个日志

    //todo：是不是要把日志回写到外存


    //调用后端
    private SenderProxy sender;


    public JPanel getMyTelemeteringJPanel()
    {
        telemeteringJPanel = new JPanel(null);
        telemeteringJPanel.setBounds(0, 0, 800, 600);
//        sender.setListener(TelemeteringJPanel.this);


        initMyLogicData();//初始化开关表
        initMyTopJPanel();
        initMyBottomJPanel();
        //这条语句只能在加载完MyTopJPanel后调用……
        currentSite = XMLReaderUtil.getSite(baseSelectComboBox.getSelectedItem().toString(),siteSelectComboBox.getSelectedItem().toString());
        initMySender();//初始化sender对象
        telemeteringJPanel.add(topJPanel);
        telemeteringJPanel.add(bottomJPanel);
        return telemeteringJPanel;
    }

    private void initMyTopJPanel()
    {

        topJPanel = new JPanel(null);//绝对布局
        topJPanel.setPreferredSize(new Dimension(800, 100));
        topJPanel.setBounds(0, 0, 800, 100);

        baseSelectLabel = new JLabel("基地选择:");
        baseSelectLabel.setBounds(100, 35, 100, 30);

        baseSelectComboBox = new JComboBox();
        baseSelectComboBox.setBounds(200, 35, 150, 30);

        for (String baseName : basesNames) {
            baseSelectComboBox.addItem(baseName);
        }

        //添加默认的 deviceFlag-dtu 的映射表
//        sender.setDtuTable(basesNames.get(0));

        //用lambda表达式重构了匿名内部类
        //当baseSelectComboBox发生改变，更新siteSelectComboBox中的条目
        baseSelectComboBox.addItemListener((itemStateChanged)->updateSiteSelectComboBox());


        siteSelectLabel = new JLabel("站点选择:");
        siteSelectLabel.setBounds(445, 35, 100, 30);


        siteSelectComboBox = new JComboBox();
        siteSelectComboBox.setBounds(545, 35, 150, 30);

        //用lambda表达式重构了匿名内部类
        siteSelectComboBox.addItemListener((itemStateChanged)->{
            if(itemStateChanged.getStateChange() == ItemEvent.SELECTED)
            {
                refreshMyPanel();
                refreshMyLog();
            }
        });

        updateSiteSelectComboBox();

        topJPanel.add(baseSelectLabel);
        topJPanel.add(baseSelectComboBox);
        topJPanel.add(siteSelectLabel);
        topJPanel.add(siteSelectComboBox);

    }

    private void initMyBottomJPanel()
    {
        bottomJPanel = new JPanel(null);
        bottomJPanel.setPreferredSize(new Dimension(800, 500));
        bottomJPanel.setBounds(0, 100, 800, 500);
        JLabel swtichLabel = new JLabel("遥测信息发送开关：");
//        swtichLabel.setIcon(imgIcon);
        swtichLabel.setBounds(100, 0, 200, 40);

        //根据mSwitchFlag初始化button样式
        boolean mSwitchFlag = getCurrentSwitchFlag();
        mSwitch.setText("关");
        mSwitch.setBounds(615, 5, 80, 30);

        //用lamda表达式重构了匿名内部类
        mSwitch.addActionListener((actionPerformed)->
                {
                    //获取当前应该开还是关
                    boolean mUpdatedSwitchFlag = getCurrentSwitchFlag();
                    if (mUpdatedSwitchFlag)
                    {
                        //清除设备
                        //直接通知外部关掉此设备！
                        closeCurrentSite();
                        setCurrentSwitchFlag(false);//回写标识

                        //改变样式：
                        mSwitch.setText("开");
                        mSwitch.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.green));
                    } else
                    {
                        //注册设备
                        registerCurrentSite();
                        setCurrentSwitchFlag(true);//回写标识

                        //改变样式:
                        mSwitch.setText("关");
                        mSwitch.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.red));
                    }
                });


        JLabel logHistoryLabel = new JLabel("遥测信息发送日志：");
        logHistoryLabel.setBounds(100, 40, 200, 40);

        JList logHistoryJList = new JList();

        logHistoryJList.setModel(mListData);
        logHistoryJList.setAutoscrolls(true);

        JScrollPane mLogScrollPane = new JScrollPane(logHistoryJList);//将Jlist填充至滚动框
        mLogScrollPane.setSize(new Dimension(600, 280));
        mLogScrollPane.setBounds(100, 100, 600, 280);

        logHistoryJList.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {

                if (e.getClickCount() == 2)
                {
                    System.out.println(TelemeteringBottomJPanel.class.getName()+"双击" + logHistoryJList.getSelectedValue());
                    //只需填充第二个参数和第三个参数（分别为弹窗内容、弹窗标题）
                    JOptionPane.showMessageDialog(telemeteringJPanel, ((LogItem)logHistoryJList.getSelectedValue()).detail(), "日志详情", JOptionPane.INFORMATION_MESSAGE);
                }
            }
        });
        bottomJPanel.add(mSwitch);
        bottomJPanel.add(mLogScrollPane);
        bottomJPanel.add(logHistoryLabel);
        bottomJPanel.add(swtichLabel);
    }

    //初始化我的逻辑数据
    private void initMyLogicData()
    {
        basesNames = XMLReaderUtil.getBasesNames();
        //我设想的是用这个switchFlagses（二维的）来维护新选择的界面到底是显示开还是关。
        //根据逻辑，所有站点的switch在程序运行时都是默认打开的，所以我填充nxm个true
        switchFlagses = new ArrayList<>();
        for(int i = 0;i <basesNames.size();i++)
        {
            ArrayList<Boolean> switchFlags = new ArrayList<>();
            for(int j = 0; j <XMLReaderUtil.getSites(basesNames.get(i)).size();j++)
            {

                switchFlags.add(new Boolean(true));
            }
            switchFlagses.add(switchFlags);
        }
    }

    //在程序启动时调用，初始化Sender对象
    private void initMySender()
    {
        sender.init(XMLReaderUtil.getMapFromBaseName(basesNames.get(0)));
        sender.register();
        //在程序加载时，默认选中的那个base必定是第一个。
        // 读取龙哥想要的，放入treemap
        sender.start();
    }

    //这个函数应该在siteSelectComboBox的【在选项】发生时调用，刷新界面
    private void refreshMyPanel()
    {
        //更新一下“当前站点”缓存中的内容
        currentSite = XMLReaderUtil.getSite(baseSelectComboBox.getSelectedItem().toString(),siteSelectComboBox.getSelectedItem().toString());
        //开关的状态
        if(getCurrentSwitchFlag())
        {
            mSwitch.setText("关");
            mSwitch.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.red));
        }
        else
        {
            mSwitch.setText("开");
            mSwitch.setUI(new BEButtonUI().setNormalColor(BEButtonUI.NormalColor.green));
        }
    }

    private void refreshMyLog()
    {
        //日志清理？
        if (mLogDetails.size()>=maxListSize)
        {
            mLogDetails.remove(0);//去掉首位，List每remove掉一个元素以后，后面的元素都会向前移动
        }

        mListData.removeAllElements();
        for (Map<String,String> logMap:mLogDetails)
        {
            if (logMap.get("设备标识符").equals(currentSite.getDeviceId()))
            {
                LogItem logItem = new LogItem(logMap);

//                String log = logMap.get("创建时间")+"   "+logMap.get("数据包类型")+"   "+logMap.get("设备标识符")+"   "+logMap.get("设备类型")+"   "+"数据长"+logMap.get("数据长度")+
//                        "   "+logMap.get("数据");

                mListData.add(0,logItem);

            }
        }
    }

    private void updateSiteSelectComboBox()
    {
        siteSelectComboBox.removeAllItems();//先清除再添加！
        Vector<XMLSite> sites = XMLReaderUtil.getSites(baseSelectComboBox.getSelectedItem().toString().trim());
        for (XMLSite site : sites) {
            siteSelectComboBox.addItem(site.getName());
        }
    }

    /**
     * onMsgListener回调方法的实现，每当接收到新日志时执行。
     * @param message
     * @param logMap
     */
    @Override
    public void handleMessage(String message, Map<String, String> logMap) {
        if(logMap!=null)
        {
            mLogDetails.add(logMap);
            refreshMyLog();//每次来要刷新
        }
    }

    //留出几个供外部调用的接口

    /**①
     * 关闭当前选中的site
     */
    public void closeCurrentSite()
    {
        String baseName = baseSelectComboBox.getSelectedItem().toString();
        String siteName = siteSelectComboBox.getSelectedItem().toString();
        XMLSite xmlSite = XMLReaderUtil.getSite(baseName, siteName);
        System.out.println("deleteDevice"+xmlSite.getDeviceId());
        sender.deleteDevice(Integer.parseInt(xmlSite.getDeviceId()));
    }
    /**②
     * 注册当前选中的site
     */
    public void registerCurrentSite()
    {
        String baseName = baseSelectComboBox.getSelectedItem().toString();
        String siteName = siteSelectComboBox.getSelectedItem().toString();
        XMLSite xmlSite = XMLReaderUtil.getSite(baseName, siteName);
        sender.register(Integer.parseInt(xmlSite.getDeviceId()), DeviceType.VEGETABLE_GREENHOUSES);
        sender.start();
    }

    /**
     * ③
     * 用来供外部在对开关进行完点击操作后回写switchFlagses
     * @param switchFlag
     */
    public void setCurrentSwitchFlag(boolean switchFlag)
    {
        //@error:也许是多余的，这里不知道get是深引用吗？存疑
        ArrayList<Boolean> t = switchFlagses.get(baseSelectComboBox.getSelectedIndex());
        t.set(siteSelectComboBox.getSelectedIndex(),new Boolean(switchFlag));
        switchFlagses.set(baseSelectComboBox.getSelectedIndex(),t);
    }

    /**
     * ④
     * 取得当前所选页的开关状态
     */
    public boolean getCurrentSwitchFlag()
    {
        return switchFlagses.get(baseSelectComboBox.getSelectedIndex()).get(siteSelectComboBox.getSelectedIndex()).booleanValue();
    }


}
